/*
 * @Author: kadu
 * @Date: 2021-06-26 12:43:26
 * @LastEditTime: 2021-06-26 22:07:35
 * @LastEditors: Please set LastEditors
 * @Description: In User Settings Edit
 * 
 *         
        EventSystem.on("change", (a: any, b: any) => {
            console.log(a);
            console.log(b);
        }, this);
        EventSystem.dispatch("change", 3, 10)
*
 */

import { TimerManager } from "../base/TimerManager";

export class EventSystem {

    private handlers: { [name: string]: { handler: Function, target: any }[] } = {};
    private eventQueue: Array<any> = [];
    // private eventQueueEx: Array<any> = [];

    private static _inst: EventSystem;
    private static get inst(): EventSystem {
        if (this._inst) {
            return this._inst;
        }
        this._inst = new EventSystem();
        return this._inst;
    }

    public constructor() {
        TimerManager.inst.addUpdate(this);
    }

    /**
     * 监听事件
     * @param eventName 
     * @param handler  
     * @param target 
     * @returns 
     */
    public static on(eventName: string, handler: Function, target?: any) {
        const handlers = this.inst.handlers;
        let handlerList = handlers[eventName];

        /**
         * 重复不要添加
         */
        if (handlerList) {
            for (var i = 0; i < handlerList.length; i++) {
                let temp = handlerList[i];
                if (temp.handler == handler && temp.target == target) {
                    return;
                }
            }
        }
        else {
            handlerList = [];
            handlers[eventName] = handlerList;
        }

        handlerList.push({ handler: handler, target: target });
        return handlerList.length;
    };

    /**
     * 取消监听事件
     * @param eventName 
     * @param handler 
     * @param target 
     * @returns 
     */
    public static off(eventName: string, handler: Function, target?: any) {
        const handlerList = this.inst.handlers[eventName];
        if (!handlerList) {
            return;
        }
        for (let i = 0; i < handlerList.length; i++) {
            const temp = handlerList[i];
            if (temp.handler === handler && temp.target === target) {
                handlerList.splice(i, 1);
                break;
            }
        }
    }

    /**
     * 取消监听事件
     * @param target 
     */
    public static offAll(target: any) {
        const handlers = this.inst.handlers;
        for (let key in handlers) {
            const handlerList = handlers[key];
            let i = 0;
            while (i < handlerList.length) {
                const oldObj = handlerList[i];
                if (target === oldObj.target) {
                    handlerList.splice(i, 1);
                }
                else {
                    ++i;
                }
            }
        }
    }

    /**
     * 派发事件
     * @param eventName 
     * @param args 
     * @returns 
     */
    public static dispatch(eventName: string, ...args: any) {
        this.inst.eventQueue.push({ eventName: eventName, args: args });
    }


    /**
     * 更新事件
     */
    private update() {
        if (this.eventQueue.length > 0) {
            let eventQueue = this.eventQueue;
            let i = 0;
            while (i < eventQueue.length) {
                let eventName = eventQueue[i].eventName;
                let args = eventQueue[i].args;
                this.handleEvent(eventName, args);
                ++i;
            }
            eventQueue.splice(0, this.eventQueue.length);
        }
    }

    /**
     * 处理事件
     * @param eventName 
     * @param args 
     * @returns 
     */
    private handleEvent(eventName: string, args: any[]) {

        const handlerList = this.handlers[eventName];

        if (!handlerList) {
            return;
        }

        for (let i = 0; i < handlerList.length; i++) {
            const objHandler = handlerList[i];
            if (objHandler.handler) {
                objHandler.handler.apply(objHandler.target, args);
            }
        }
    }

}